package org.yaukie.core.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaukie.ClassCacheFactory;
import org.yaukie.core.BaseJob;
import org.yaukie.core.anotation.MyJob;
import org.yaukie.core.api.MyJobInter;
import org.yaukie.helper.ConfigHelper;

import java.text.ParseException;
import java.util.List;
import java.util.Map;


/**
 * @Author: yuenbin
 * @Date :2020/5/16
 * @Time :9:51
 * @Motto: It is better to be clear than to be clever !
 * @Destrib: 定时任务主操作入口
 **/
public class MyJobInstance extends MyAbstractJob implements MyJobInter {

    private static final Logger log = LoggerFactory.getLogger(MyJobInstance.class);


    /**
     * 根据时间规则，启动一个作业
     *
     * @param jobClass
     * @param cron
     * @throws SchedulerException
     */
    @Override
    public void startJob(Class jobClass, String cron) {
        //已经启动的作业,不再启动
        if (getJobStatus(jobClass)) {
            return;
        }
        Trigger trigger = createJobTrigger(jobClass, cron);
        JobDetail jobDetail = createJobDetail(jobClass);
        doStartJob(jobClass, jobDetail, trigger);
    }

    @Override
    public void startJob(Class jobClass, int seconds) {
        startJob(jobClass, 0, seconds);
    }

    @Override
    public void startJob(Class jobClass, int count, int seconds) {
        startJob(jobClass, count, seconds, null, null);
    }

    @Override
    public void startJob(Class jobClass, int count, int seconds, String start, String end) {
        Trigger trigger = createJobSimpleTriger(jobClass, count, seconds, start, end);
        JobDetail jobDetail = createJobDetail(jobClass);
        doStartJob(jobClass, jobDetail, trigger);
    }


    /**
     * 启动所有含有Job注解的所有定时任务
     * 注意,需要指定要扫描的基础包路径
     */
    @Override
    public void startAllJob() {
        List<Class<?>> classList = ClassCacheFactory.getClassSupportApi().
                getClassListBySuper(ConfigHelper.getAppBasePackage(), BaseJob.class);
        if(null != classList && classList.size() > 0 ){
            log.debug("检测到总共【"+classList.size()+"】个定时任务！");
            for(int index=0;index < classList.size();index++){
                Class cls = classList.get(index) ;
                //如果被Job注解,则根据类型启动定时器
                if (cls.isAnnotationPresent(MyJob.class)) {
                    log.debug("正在启动第"+(index+1)+"个，[ " + cls.getSimpleName() + " ]定时任务");
                    MyJob job = (MyJob) cls.getAnnotation(MyJob.class);
                    MyJob.JobType jobType = job.jobType();
                    //如果是时间规则
                    if (jobType.equals(MyJob.JobType.CRON)) {
                        String cron = job.value();
                        startJob(cls, cron);
                        //如果是时间间隔类型
                    } else if (jobType.equals(MyJob.JobType.TIMER)) {
                        startJob(cls, job.count(), job.seconds(), job.start(), job.end());
                    }
                }
            }

        }


    }


    /**
     * 关闭一个作业
     *
     * @param jobClass
     */
    @Override
    public void stopJob(Class jobClass) {
        Scheduler scheduler = schedulerMap.get(jobClass);
        try {
            scheduler.shutdown(true);
            schedulerMap.remove(jobClass);
        } catch (SchedulerException e) {
            log.error("shutdown job " + jobClass.getSimpleName() + " error ");
        }
    }

    /**
     * 关闭所有job
     */
    @Override
    public void stopAllJob() {
        if (log.isDebugEnabled()) {
            log.debug("shutdown all jobs start....");
        }
        for (Map.Entry<Class, Scheduler> entry : schedulerMap.entrySet()) {
            Class jobClass = entry.getKey();
            Scheduler scheduler = entry.getValue();
            try {
                scheduler.shutdown(true);
                schedulerMap.remove(jobClass);
            } catch (SchedulerException e) {
                log.error("shutdown job " + jobClass.getSimpleName() + " error ");
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("shutdown all jobs end ....");
        }

    }


    /**
     * 暂停一个job
     *
     * @param jobClass
     * @throws SchedulerException
     */
    @Override
    public void pauseJob(Class jobClass) throws SchedulerException {
        Scheduler scheduler;
        if (schedulerMap.containsKey(jobClass)) {
            scheduler = schedulerMap.get(jobClass);
            scheduler.pauseJob(new JobKey(jobClass.getName()));
        }

    }

    /**
     * 启动一个job
     *
     * @param jobClass
     * @throws SchedulerException
     */
    @Override
    public void resumeJob(Class jobClass) throws SchedulerException {
        Scheduler scheduler;
        if (schedulerMap.containsKey(jobClass)) {
            scheduler = schedulerMap.get(jobClass);
            scheduler.resumeJob(new JobKey(jobClass.getName()));
        }

    }


    /**
     * 创建作业实例
     *
     * @param jobClass
     * @return
     */

    private static JobDetail createJobDetail(Class jobClass) {
        return JobBuilder.newJob((Class<? extends org.quartz.Job>) jobClass).withIdentity(jobClass.getName()).build();
    }


    /**
     * 创建基于次数的触发器实例
     * 每隔几秒执行一个作业 并指定重复次数
     *
     * @param jobClass
     * @param seconds
     * @return
     */
    private SimpleTrigger createJobSimpleTriger(Class jobClass, int count, int seconds) {
        return createJobSimpleTriger(jobClass, count, seconds, null, null);
    }

    /**
     * 创建基于时间的触发器实例
     * 每隔几秒执行一个作业
     *
     * @param jobClass
     * @param seconds
     * @return
     */
    private SimpleTrigger createJobSimpleTriger(Class jobClass, int seconds) {
        return createJobSimpleTriger(jobClass, 0, seconds, null, null);
    }


    /**
     * 根据情况选择作业执行
     *
     * @param triggerBuilder
     * @param start
     * @param end
     * @return
     */
    @Override
    SimpleTrigger doCreateJobSimpleTrigger(TriggerBuilder<SimpleTrigger> triggerBuilder, String start, String end) {

        if (StringUtils.isNotEmpty(start)) {
            try {
                triggerBuilder.startAt(DateUtils.parseDate(start, "yyyy-MM-dd HH:mm:ss"));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        if (StringUtils.isNotEmpty(start)) {
            try {
                triggerBuilder.startAt(DateUtils.parseDate(end, "yyyy-MM-dd HH:mm:ss"));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        return triggerBuilder.build();

    }

    /**
     * 创建调度实例
     *
     * @param jobDetail
     * @param trigger
     * @return
     * @throws SchedulerException
     */
    @Override
    public  Scheduler createScheduler(JobDetail jobDetail, Trigger trigger) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.setJobFactory(new JobFactory() {
            @Override
            public Job newJob(TriggerFiredBundle triggerFiredBundle, Scheduler scheduler) throws SchedulerException {
                JobDetail jobDetail = triggerFiredBundle.getJobDetail();
                Class jobClass = jobDetail.getJobClass();
                try {
                    return (Job) jobClass.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
        scheduler.scheduleJob(jobDetail, trigger);
        return scheduler;
    }

    /**
     * 获取调度实例
     *
     * @param jobClass
     * @return
     */
    @Override
    Scheduler getScheduler(Class jobClass) {
        Scheduler scheduler = null;
        if (schedulerMap.containsKey(jobClass)) {
            scheduler = schedulerMap.get(jobClass);
        }
        return scheduler;
    }


}
